#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <sys/stat.h>
#include <signal.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include "doorinfo.h"

int mysocket = 0;
FILE *outstream;
FILE *instream;

int timeout = 0;
int timeleft = 0;
int warned = 0;

extern int door_main(void);
extern void door_quit(void);

struct dorinfo_t door_info;

void signal_handler(int sig);

int drprintf(const char *format, ...) {
	int ret;

	va_list ap;
        va_start(ap, format);

		if (mysocket == -1 ) {
			ret = vfprintf(stdout, format, ap);
		} else {
			ret = vfprintf(outstream, format, ap);
		}
        va_end(ap);
	fflush(outstream);

	return ret;
}


char drgetc() {
	int c;
		
	if (mysocket == -1) {
		c = fgetc(stdin);
	} else {
		c = fgetc(instream);
		if (feof(instream)) {
			exit(-1);
		}
	}
	
	if (c != -1) {
		timeout = time(NULL);
	}
	
	return c;
}
int yesno(void) {
	int c;
	while (1) {
		c = drgetc();
		if (c == 'Y' || c == 'y') {
			return 1;
		} else if (c == 'N' || c == 'n') {
			return 0;
		}
		if (c == -1) {
			usleep(100);
		}
	}
}

int read_int(void) {
	char buffer[64];
	int i;
	int ret = 0;
	
	read_line(buffer, 64);
	
	for (i=0;i<strlen(buffer);i++) {
		if (buffer[i] >= '0' && buffer[i] <= '9') {
			ret = ret * 10 + (buffer[i] - '0');
		}
	}
	
	return ret;
}

int read_line(char* buffer, int len) {
	int c;
	int l;
	
	l = 0;
	
	while (1) {
		if (l == len) {
			break;
		}
		
		c = drgetc();
		while (c == -1) {
			usleep(100);
			c = drgetc();
		}
		
		
		if (c == '\r' || c == '\n') {
			break;
		}
		
		if (c == '\b' || c == 127) {
			if (l > 0) {
				l--;
				buffer[l] = '\0';
				drprintf("\e[1D \e[1D");
			}
		} else if (c > 31 && c < 127) {
			drprintf("%c", c);
			buffer[l] = c;
			buffer[l+1] = '\0';
			l++;			
		}
	}
	return l;
}

void load_doorfile(char *filename) {
	// load door file
	FILE *dptr;
	char buffer[256];
	int i;
	
	dptr = fopen(filename, "r");
	
	if (!dptr) {
		fprintf(stderr, "Error opening DORINFO1.DEF @ %s\n", filename);
		exit(-2);
	}
	
	fgets(buffer, 256, dptr);
	
	for (i=strlen(buffer)-1; i>strlen(buffer)-3;i--) {
		if (buffer[i] == '\n' || buffer[i] == '\r') {
			buffer[i] = '\0';
		}
	}
	strncpy(door_info.bbsname, buffer, 64);
	
	fgets(buffer, 256, dptr);
	
	for (i=strlen(buffer)-1; i>strlen(buffer)-3;i--) {
		if (buffer[i] == '\n' || buffer[i] == '\r') {
			buffer[i] = '\0';
		}
	}
	strncpy(door_info.sysop_fname, buffer, 32);
	
	fgets(buffer, 256, dptr);
	
	for (i=strlen(buffer)-1; i>strlen(buffer)-3;i--) {
		if (buffer[i] == '\n' || buffer[i] == '\r') {
			buffer[i] = '\0';
		}
	}
	strncpy(door_info.sysop_lname, buffer, 32);
	
	fgets(buffer, 256, dptr);
	fgets(buffer, 256, dptr);
	fgets(buffer, 256, dptr);
	
	fgets(buffer, 256, dptr);
	
	for (i=strlen(buffer)-1; i>strlen(buffer)-3;i--) {
		if (buffer[i] == '\n' || buffer[i] == '\r') {
			buffer[i] = '\0';
		}
	}
	strncpy(door_info.user_fname, buffer, 32);	

	fgets(buffer, 256, dptr);
	
	for (i=strlen(buffer)-1; i>strlen(buffer)-3;i--) {
		if (buffer[i] == '\n' || buffer[i] == '\r') {
			buffer[i] = '\0';
		}
	}
	strncpy(door_info.user_lname, buffer, 32);
	fgets(buffer, 256, dptr);
	strncpy(door_info.user_location, buffer, 64);
	fgets(buffer, 256, dptr);
	fgets(buffer, 256, dptr);
		
	for (i=strlen(buffer)-1; i>strlen(buffer)-3;i--) {
		if (buffer[i] == '\n' || buffer[i] == '\r') {
			buffer[i] = '\0';
		}
	}
	
	door_info.user_level = 0;
	for (i=0;i<strlen(buffer);i++) {
		door_info.user_level = door_info.user_level * 10 + (buffer[i] - '0');
	}

	fgets(buffer, 256, dptr);
	
	for (i=strlen(buffer)-1; i>strlen(buffer)-3;i--) {
		if (buffer[i] == '\n' || buffer[i] == '\r') {
			buffer[i] = '\0';
		}
	}
	
	door_info.time_left = 0;
	for (i=0;i<strlen(buffer);i++) {
		door_info.time_left = door_info.time_left * 10 + (buffer[i] - '0');
	}

	fclose(dptr);
}

int main(int argc, char **argv) {
	int i;
	FILE *dptr;
	char buffer[256];
	int door_process;
	int return_status;
	
	if (argc < 3) {
		exit(-1);
	}
	
	if (!strcmp(argv[1], "stdio")) {
		mysocket = -1;
	} else {
		for (i=0;i<strlen(argv[1]);i++) {
			mysocket = mysocket * 10 + (argv[1][i] - '0');
		}
		
		outstream = fdopen(mysocket, "w");
		instream = fdopen(mysocket, "r");
	}
	

	
	load_doorfile(argv[2]);
	
	timeout = time(NULL);
	timeleft = time(NULL) + (door_info.time_left * 60);
	
	door_process = fork();
	
	switch (door_process) {
		case -1:
			printf("Fork error!\n");
			break;
		case 0:
			signal(SIGUSR1, signal_handler);
			exit(door_main());
			break;
		default:
			while(!waitpid(door_process, &return_status, WNOHANG)) {
				sleep(1);
				kill(door_process, SIGUSR1);
			}
			break;
	}
}

void signal_handler(int sig) {
	time_t time_now = time(NULL);
	switch(sig) {
		case SIGUSR1:
		
			if (time_now - timeout > 270 && time_now - timeout < 300) {
				if (warned == 0) {
					drprintf("Press a key in 30 seconds or connection will timeout.\r\n");
					warned = 1;
				}
			} else if (time_now - timeout >= 300) {
				drprintf("Timeout.\r\n");
				door_quit();
				exit(-3);
			} else {
				warned = 0;
			}
		
			if (time_now >= timeleft) {
				drprintf("Out of time.\r\n");
				door_quit();
				exit(-4);
			}
		
			break;
	}
}


